using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using SumerCoreDevOps.Infrastructure.Artifacts;
using System.IO;

namespace SumerCoreDevOps.ControlApi.Controllers;

/// <summary>
/// 构建产物 API
/// </summary>
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class ArtifactController : ControllerBase
{
    private readonly BuildArtifactManager _artifactManager;
    private readonly ArtifactProxyDownloadService _proxyDownloadService;
    private readonly ILogger<ArtifactController> _logger;

    public ArtifactController(
        BuildArtifactManager artifactManager,
        ArtifactProxyDownloadService proxyDownloadService,
        ILogger<ArtifactController> logger)
    {
        _artifactManager = artifactManager;
        _proxyDownloadService = proxyDownloadService;
        _logger = logger;
    }

    /// <summary>
    /// 获取产物列表（按任务 ID）
    /// </summary>
    /// <param name="taskId">任务ID</param>
    /// <returns>返回包含产物列表的成功响应，包括产物ID、名称、类型、文件大小、MD5哈希、下载URL等信息</returns>
    [HttpGet("task/{taskId}")]
    public async Task<IActionResult> GetByTaskId(long taskId)
    {
        try
        {
            var artifacts = await _artifactManager.GetArtifactsByTaskIdAsync(taskId);
            return Ok(new
            {
                success = true,
                data = artifacts.Select(a => new
                {
                    a.Id,
                    a.Name,
                    a.Type,
                    a.FileSize,
                    a.Md5Hash,
                    a.Description,
                    a.CreatedAt,
                    a.ExpiresAt,
                    a.DownloadCount,
                    DownloadUrl = $"/api/artifact/download/{a.Id}"
                }),
                timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取产物列表失败: TaskId={TaskId}", taskId);
            return StatusCode(500, new
            {
                success = false,
                errorMessage = "获取产物列表失败",
                timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
            });
        }
    }

    /// <summary>
    /// 获取产物列表（按构建历史 ID）
    /// </summary>
    /// <param name="buildHistoryId">构建历史ID</param>
    /// <returns>返回包含产物列表的成功响应，包括产物ID、名称、类型、文件大小、MD5哈希、下载URL等信息</returns>
    [HttpGet("build/{buildHistoryId}")]
    public async Task<IActionResult> GetByBuildHistoryId(long buildHistoryId)
    {
        try
        {
            var artifacts = await _artifactManager.GetArtifactsByBuildHistoryIdAsync(buildHistoryId);
            return Ok(new
            {
                success = true,
                data = artifacts.Select(a => new
                {
                    a.Id,
                    a.Name,
                    a.Type,
                    a.FileSize,
                    a.Md5Hash,
                    a.Description,
                    a.CreatedAt,
                    a.ExpiresAt,
                    a.DownloadCount,
                    DownloadUrl = $"/api/artifact/download/{a.Id}"
                }),
                timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取产物列表失败: BuildHistoryId={BuildHistoryId}", buildHistoryId);
            return StatusCode(500, new
            {
                success = false,
                errorMessage = "获取产物列表失败",
                timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
            });
        }
    }

    /// <summary>
    /// 下载构建产物（通过 TCP 代理从执行节点获取）
    /// </summary>
    /// <param name="id">产物ID</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>返回产物文件流，如果产物不存在返回404，如果已过期返回410，如果无法从执行节点下载返回503</returns>
    [HttpGet("download/{id}")]
    public async Task<IActionResult> Download(long id, CancellationToken cancellationToken)
    {
        try
        {
            var artifact = await _artifactManager.GetArtifactAsync(id);

            if (artifact == null)
            {
                return NotFound(new
                {
                    success = false,
                    errorMessage = "产物不存在或已删除",
                    timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
                });
            }

            // 检查是否已过期
            if (artifact.ExpiresAt.HasValue && artifact.ExpiresAt.Value < DateTime.UtcNow)
            {
                return StatusCode(410, new
                {
                    success = false,
                    errorMessage = "产物已过期",
                    timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
                });
            }

            // 通过 TCP 代理从执行节点下载文件
            var stream = await _proxyDownloadService.DownloadArtifactAsync(id, cancellationToken);

            if (stream == null)
            {
                return StatusCode(503, new
                {
                    success = false,
                    errorMessage = "无法从执行节点下载产物文件（节点可能离线或文件不存在）",
                    timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
                });
            }

            // 增加下载次数
            await _artifactManager.IncrementDownloadCountAsync(id);

            _logger.LogInformation("下载产物: Id={Id}, Name={Name}, NodeId={NodeId}",
                id, artifact.Name, artifact.NodeId);

            // 返回文件流
            var contentType = GetContentType(artifact.Type);
            return File(stream, contentType, artifact.Name);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "下载产物失败: Id={Id}", id);
            return StatusCode(500, new
            {
                success = false,
                errorMessage = "下载失败",
                timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
            });
        }
    }

    /// <summary>
    /// 删除产物
    /// </summary>
    /// <param name="id">产物ID</param>
    /// <returns>返回删除成功响应，如果产物不存在返回404</returns>
    [HttpDelete("{id}")]
    public async Task<IActionResult> Delete(long id)
    {
        try
        {
            var artifact = await _artifactManager.GetArtifactAsync(id);

            if (artifact == null)
            {
                return NotFound(new
                {
                    success = false,
                    errorMessage = "产物不存在",
                    timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
                });
            }

            // 删除物理文件
            if (System.IO.File.Exists(artifact.FilePath))
            {
                System.IO.File.Delete(artifact.FilePath);
            }

            // 软删除数据库记录
            await _artifactManager.DeleteArtifactAsync(id);

            _logger.LogInformation("删除产物: Id={Id}, Name={Name}", id, artifact.Name);

            return Ok(new
            {
                success = true,
                data = new { id },
                timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "删除产物失败: Id={Id}", id);
            return StatusCode(500, new
            {
                success = false,
                errorMessage = "删除失败",
                timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
            });
        }
    }

    /// <summary>
    /// 获取产物统计信息
    /// </summary>
    /// <returns>返回产物统计数据，包括总数、总大小、各类型数量等信息</returns>
    [HttpGet("statistics")]
    public async Task<IActionResult> GetStatistics()
    {
        try
        {
            var stats = await _artifactManager.GetStatisticsAsync();
            return Ok(new
            {
                success = true,
                data = stats,
                timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取产物统计信息失败");
            return StatusCode(500, new
            {
                success = false,
                errorMessage = "获取统计信息失败",
                timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
            });
        }
    }

    private string GetContentType(string type)
    {
        return type.ToLower() switch
        {
            "zip" => "application/zip",
            "tar.gz" or "tgz" => "application/gzip",
            "tar" => "application/x-tar",
            "jar" => "application/java-archive",
            "war" => "application/java-archive",
            "dll" => "application/octet-stream",
            "exe" => "application/octet-stream",
            _ => "application/octet-stream"
        };
    }
}
